package com.thtfpc.discovery;

import com.thtfpc.ssdp.*;
import com.thtfpc.utility.InetUtil;

import java.io.IOException;
import java.lang.ref.WeakReference;
import java.net.*;
import java.util.*;
import java.util.logging.Logger;

public class ScreenPlayer extends SSDPChannel {

    public interface RenderRequestListener {
        int onRequestRender(RenderRequest renderRequest);
    }

    public static class RenderRequest {
        public String sessionId;
        public String mediaURL;
        public String hostAddress;
        public int port;

        @Override
        public String toString() {
            return "RenderRequest{" +
                    "sessionId='" + sessionId + '\'' +
                    ", mediaURL='" + mediaURL + '\'' +
                    ", hostAddress='" + hostAddress + '\'' +
                    ", port=" + port +
                    '}';
        }
    }

    public static String TAG = ScreenPlayer.class.getSimpleName();
    public static Logger logger = Logger.getLogger(ScreenPlayer.class.getSimpleName());

    protected SimpleServiceDeclarer simpleServiceDeclarer;
    protected String id;
    protected WeakReference<RenderRequestListener> renderListener;

    public ScreenPlayer(RenderRequestListener renderListenr) {
        this(19033, renderListenr);
    }

    public ScreenPlayer(int port, RenderRequestListener renderListenr) {
        super(port, false);
        this.port = port;
        id = UUID.randomUUID().toString();
        simpleServiceDeclarer = new SimpleServiceDeclarer();
        this.renderListener = new WeakReference<>(renderListenr);
    }

    @Override
    protected void onStart() {
        super.onStart();
        /*
        发布ScreenRender响应服务
         */
        SSDPDevice renderDevice = new SSDPDevice();
        renderDevice.setName("urn:schemas-upnp-org:device:MediaRenderer:1");
        renderDevice.setId(id);
        String deviceAddress = null;
        String deviceName = InetUtil.getHostName();
        try {
            deviceAddress = InetUtil.getLocalHostAddress().getHostAddress();
        }
        catch (UnknownHostException ex) {
            deviceAddress = "127.0.0.1";
            ex.printStackTrace();
        }
        renderDevice.setTitle(deviceName);
        renderDevice.setAddress(deviceAddress);
        renderDevice.setServiceUrl(deviceAddress + ":" + this.port);
        renderDevice.setPort(this.port);
        this.simpleServiceDeclarer.registerService(renderDevice);
        try {
            this.simpleServiceDeclarer.start();
        }
        catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        this.simpleServiceDeclarer.unregisterService("urn:schemas-upnp-org:device:MediaRenderer:1");
        try {
            this.simpleServiceDeclarer.stop();
        }
        catch (IOException ex) {
        }
    }

    @Override
    protected void onMessage(SSDPMessage message) {
        if ("SCR-RENDER * HTTP/1.1".equals(message.getMessageType())) {
            //ACTION: SCREEN_RENDER_REQ
            //USN: uuid:xxx-xxx-xx
            //RT: urn:schemas-upnp-org:device:MediaRenderer:1 (RequestTarget)
            //LOCATION: rtps://xxxxx/xxx
            final String action = message.getHeader("ACTION");
            final String uuid = message.getHeader("USN");
            final String sessionId = message.getHeader("SESSION");
            final String reqestTarget = message.getHeader("RT");
            final String rtspUrl = message.getHeader("LOCATION");
            if (action != null
                    && uuid != null
                    && rtspUrl != null
                    && sessionId != null
                    && "SCREEN_RENDER".equals(action)
                    && uuid.endsWith(this.id)) {
                RenderRequest renderRequest = new RenderRequest();
                renderRequest.hostAddress = message.getAddress();
                renderRequest.port = message.getPort();
                renderRequest.mediaURL = rtspUrl;
                renderRequest.sessionId = sessionId;
                onClientRequestRender(renderRequest);
            }
        }
    }

    protected void onClientRequestRender(RenderRequest renderRequest) {
        RenderRequestListener renderRequestListener = this.renderListener.get();
        if (renderRequestListener != null) {
            int result = renderRequestListener.onRequestRender(renderRequest);
            SSDPMessage messageSend = new SSDPMessageBuilder()
                    .messageType("HTTP/1.1 200 OK")
                    .header("ACTION", "SCREEN_RENDER")
                    .header("RESULT", String.valueOf(result))
                    .header("SESSION", renderRequest.sessionId)
                    .header("USN", id)
                    .address(renderRequest.hostAddress)
                    .port(renderRequest.port)
                    .build();
            sendMessage(messageSend);
        }
    }
}
